package com.iot08.api.service;

import com.iot08.api.response.*;
import com.iot08.api.vo.request.*;
import com.iot08.api.vo.request.base.BodyFormAccount;
import com.iot08.common.entity.app.GoldCoinProductInfo;
import com.iot08.common.entity.app.PayOrderInfo;
import com.iot08.common.entity.app.ProductInfo;
import com.iot08.common.entity.app.StartEndTime;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.DateUtil;
import com.iot08.common.utils.response.ResponseEnum;
import com.iot08.common.utils.response.ResponseMap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author cwj
 * @description
 * @date 2024/12/29 11:48
 **/
@Slf4j
@Service
public class PayOrderInfoService extends BaseService<PayOrderInfo> {

    @Resource
    private VipMemberService vipMemberService;

    @Resource
    private ProductInfoService productInfoService;

    /**
     * @description 创建订单信息
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/12/29 17:25
     **/
    public ResponseMap createOrder(CreatePaymentReqBodyFormVO vo) {
        //查询产品信息
        ProductInfo productInfo = productInfoService.findById(new ObjectId(vo.getPid()));
        if(ObjectUtils.isEmpty(productInfo)){
            return ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.payment.product.notExists");
        }
        if(vo.getCurrency().equals(productInfo.getCurrency()) && (!productInfo.getPrice().equals(vo.getPayAmount()) || !productInfo.getOriginalPrice().equals(vo.getOriginalCost()))){
            return ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.payment.product.price.error");
        }
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        //创建会员支付订单
        String orderid = createPayOrderInfo(vo, productInfo,productInfo.getPrice(),null, UUID.randomUUID().toString(),0);
        if(StringUtils.isNotEmpty(orderid)){
            //创建或更新会员
            vipMemberService.createOrUpdateVipMember(vo, productInfo.getType(),orderid);
        }
        ResponseMap res = ResponseMap.success();
        //创建或更新vip记录
        res.put("orderid",payOrderInfo.getId());
        return res;
    }


    /**
     * @description 创建商品订单
     * @author cwj
     * @param [vo, productInfo, amount, ipAddr, appAccountToken, orderType]
     * @return java.lang.String
     * @date @time 2024/12/30 16:37
     **/
    public String createPayOrderInfo(CreatePaymentReqBodyFormVO vo, ProductInfo productInfo, BigDecimal amount, String ipAddr, String appAccountToken, Integer orderType) {
        PayOrderInfo order = new PayOrderInfo();
        order.setOpenid(vo.getOpenid());
        order.setPId(vo.getPid());
        order.setOrderType(orderType);
        order.setPayAmount(amount);
        order.setProductInfo(productInfo.getName());
        order.setProductType(productInfo.getType());
        order.setOriginalCost(productInfo.getOriginalPrice());
        order.setPaymentMethod(vo.getPayType());
        order.setAppAccountToken(appAccountToken);
        order.setRemark("创建订单,开始支付");
        order.setOrderStatus(0);
        order.setPaymentStatus(0);
        order.setPayIp(ipAddr);
        order.setOrderTime(DateUtil.dateToStr(new Date(),DateUtil.FORMAT_1));
        order.setCurrency(StringUtils.isEmpty(vo.getCurrency())? productInfo.getCurrency(): vo.getCurrency());
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setCreateTimestamp(new Date().getTime());
        this.save(order);
        return order.getId();
    }

    /**
     * @description 创建金币的支付订单
     * @author cwj
     * @param [vo, goldCoin, ipAddr, appAccountToken, orderType]
     * @return java.lang.String
     * @date @time 2025/3/6 11:50
     **/
    public String createGoldCoinPayOrderInfo(CreateGoldCoinPaymentReqBodyFormVO vo, GoldCoinProductInfo goldCoin,BigDecimal payAmount, String ipAddr,
                                             String appAccountToken, Integer orderType) {
        PayOrderInfo order = new PayOrderInfo();
        order.setOpenid(vo.getOpenid());
        order.setPId(vo.getGid());
        order.setOrderType(orderType);
        order.setPayAmount(payAmount);
        order.setGoldCoinNum(goldCoin.getGoldCoinNum());
        order.setProductInfo(goldCoin.getName());
        order.setProductType(goldCoin.getType());
        order.setPaymentMethod(vo.getPayType());
        order.setAppAccountToken(appAccountToken);
        order.setRemark("创建订单,开始支付");
        order.setOrderStatus(0);
        order.setPaymentStatus(0);
        order.setPayIp(ipAddr);
        order.setOrderTime(DateUtil.dateToStr(new Date(),DateUtil.FORMAT_1));
        order.setCurrency(goldCoin.getCurrency());
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        order.setCreateTimestamp(new Date().getTime());
        this.save(order);
        return order.getId();

    }

    /**
     * @description 保存支付订单
     * @author cwj
     * @param [vo, payOrderInfo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/12/30 10:03
     **/
    public ResponseMap savePayOrderInfo(CreatePaymentReqBodyFormVO vo, PayOrderInfo payOrderInfo) {
        Date date = DateUtil.getDate(new Date());
        payOrderInfo.setOpenid(vo.getOpenid());
        //产品id
        payOrderInfo.setPId(vo.getPid());
        payOrderInfo.setOrderTime(DateUtil.dateToStr(date,DateUtil.FORMAT_1));
        payOrderInfo.setPayAmount(vo.getPayAmount());
        payOrderInfo.setOriginalCost(ObjectUtils.isEmpty(vo.getOriginalCost())? vo.getPayAmount(): vo.getOriginalCost());
       /* payOrderInfo.setProductType(vo.getProductType());
        payOrderInfo.setProductInfo(vo.getProductInfo());*/
        payOrderInfo.setCurrency(StringUtils.isEmpty(vo.getCurrency())?"CNY": vo.getCurrency());
        payOrderInfo.setCreateTime(date);
        payOrderInfo.setUpdateTime(date);
        payOrderInfo.setCreateTimestamp(date.getTime());
        this.save(payOrderInfo);
        return ResponseMap.success();
    }


    /**
     * @description 保存订单信息
     * @author cwj
     * @param [vo]
     * @return java.lang.String
     * @date @time 2024/12/30 16:24
     **/
    public String savePayOrderInfo(PayOrderInfoVo vo) {
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        Date date = DateUtil.getDate(new Date());
        payOrderInfo.setOpenid(vo.getOpenid());
        //产品id
        payOrderInfo.setPId(vo.getPId());
        payOrderInfo.setOrderTime(DateUtil.dateToStr(date,DateUtil.FORMAT_1));
        payOrderInfo.setPayAmount(vo.getPayAmout());
        payOrderInfo.setOriginalCost(ObjectUtils.isEmpty(vo.getOriginalCost())? vo.getPayAmout(): vo.getOriginalCost());
        payOrderInfo.setProductType(vo.getProductType());
        payOrderInfo.setProductInfo(vo.getProductInfo());
        payOrderInfo.setRemark(vo.getRemark());
        payOrderInfo.setPaymentMethod(vo.getPaymentMethod());
        payOrderInfo.setCurrency(StringUtils.isEmpty(vo.getCurrency())?"RMB": vo.getCurrency());
        payOrderInfo.setCreateTime(date);
        payOrderInfo.setUpdateTime(date);
        payOrderInfo.setCreateTimestamp(date.getTime());
        this.save(payOrderInfo);
        return payOrderInfo.getId();
    }

    /**
     * @description 查询用户订单信息
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/12/29 17:16
     **/
    public ResponseMap queryPayOrderInfoService(BodyFormAccount vo){
        Query query = new Query(Criteria.where("openid").is(vo.getOpenid()));
        List<PayOrderInfoResp> payOrderInfoResps = mongoTemplate.find(query,PayOrderInfoResp.class,"pay_order_info");
        ResponseMap res = ResponseMap.success();
        res.put("payOrderInfos",payOrderInfoResps);
        return res;
    }

    /**
     * @description 查询支付订单信息
     * @author cwj
     * @param [transactionId]
     * @return com.iot08.common.entity.app.PayOrderInfo
     * @date @time 2025/1/16 17:12
     **/
    public PayOrderInfo queryPayOrderInfoByTransactionId(String transactionId){
        Query query = new Query(Criteria.where("transactionId").is(transactionId)).limit(1);
        return this.findOne(query);
    }


    /**
     * @param [vo]
     * @description 更新订单信息
     * @author cwj
     * @date @time 2024/12/29 17:39
     **/
    public void updatePayOrderInfo(PayOrderInfoUpdateVo vo){
        Update update = new Update();
        if(StringUtils.isNotEmpty(vo.getTransactionId())){
            update.set("transactionId",vo.getTransactionId());
        }
        //支付用户手机号
        if(StringUtils.isNotEmpty(vo.getPhone())){
           update.set("phone",vo.getPhone());
        }
        if(ObjectUtils.isNotEmpty(vo.getOrderStatus())){
            update.set("orderStatus",vo.getOrderStatus());
        }
        if(StringUtils.isNotEmpty(vo.getPaymentTime())){
            update.set("paymentTime",vo.getPaymentTime());
        }
        if(StringUtils.isNotEmpty(vo.getPaymentMethod())){
            update.set("paymentMethod",vo.getPaymentMethod());
        }
        if(ObjectUtils.isNotEmpty(vo.getPaymentStatus())){
            update.set("paymentStatus",vo.getPaymentStatus());
        }
        if(ObjectUtils.isNotEmpty(vo.getPayAmount())){
            log.info("vo.getPayAmount的值为：{}：",vo.getPayAmount());
            update.set("payAmount",vo.getPayAmount());
        }
        //用户实际支付金额，支付宝或微信支付补贴的，商家入账仍是支付金额
        if(ObjectUtils.isNotEmpty(vo.getRealPayAmount())){
            update.set("realPayAmount",vo.getRealPayAmount());
        }
        //商家实收金额
        if(ObjectUtils.isNotEmpty(vo.getRealReceiptAmount())){
            update.set("realReceiptAmount",vo.getRealReceiptAmount());
        }
        if(StringUtils.isNotEmpty(vo.getCurrency())){
            update.set("currency",vo.getCurrency());
        }
        if(StringUtils.isNotEmpty(vo.getPayIp())){
            update.set("payIp",vo.getPayIp());
        }
        if(StringUtils.isNotEmpty(vo.getRemark())){
            update.set("remark",vo.getRemark());
        }
        update.set("updateTime",new Date());
        this.updateById(new ObjectId(vo.getOrderid()),update);
    }
    
    /**
     * @description 更新支付订单状态为退款状态
     * @author cwj
     * @param [orderId]
     * @return void
     * @date @time 2025/2/8 11:05
     **/
    public void updatePayOrderRefundStatus(String orderId,Integer orderStatus, Integer paymentStatus) {
        Update update = new Update();
        update.set("orderStatus",orderStatus);
        update.set("paymentStatus",paymentStatus);
        update.set("updateTime",new Date());
        this.updateById(new ObjectId(orderId),update);
    }


    /**
     * @description 查询倒数第二个有效支付订单的信息
     * @author cwj
     * @param [openid]
     * @return com.iot08.common.entity.app.PayOrderInfo
     * @date @time 2025/2/19 16:35
     **/
    public PayOrderInfo queryInverseSecondPayOrderInfo(String openId,String orderId) {
        //组装查询条件
        Query query = new Query();
        query.addCriteria(Criteria.where("openid").is(openId).and("orderStatus").is(1).and("_id").ne(new ObjectId(orderId)));  // 查询条件
        query.with(Sort.by(Sort.Direction.DESC, "createTime")).limit(1);  // 按 createTime 降序排序
        //PayOrderInfo payOrderInfo = mongoTemplate.findOne(query,PayOrderInfo.class);
        return this.findOne(query);
    }

    /**
     * @description 更新订单的transactionId
     * @author cwj
     * @param [transactionId]
     * @return void
     * @date @time 2025/2/26 8:28
     **/
    public void updatePayOrderTransactionId(String orderId,String transactionId){
        Update update = new Update();
        update.set("transactionId",transactionId);
        this.updateById(new ObjectId(orderId),update);
    }

    /**
     * @description 根据AppAccountToken查询订单信息
     * @author cwj
     * @param [appAccountToken]
     * @return com.iot08.common.entity.app.PayOrderInfo
     * @date @time 2025/2/26 14:08
     **/
    public PayOrderInfo queryPayOrderInfoByAppAccountToken(String appAccountToken){
        Query query = new Query();
        query.addCriteria(Criteria.where("appAccountToken").is(appAccountToken)).limit(1);
        return this.findOne(query);
    }

    /**
     * @description 查询用户成功支付的订单记录
     * @author cwj
     * @param [vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2025/3/29 14:16
     **/
    public ResponseMap queryPayOrderInfo(PayOrderInfoQueryReqVo vo) throws ParseException {
        //构建查询时间的范围
        StartEndTime startEndTime =  DateUtil.assembleStartEndTime(vo.getDeadlineYear(),vo.getDeadlineMonth());
        Query query = new Query();
        query.addCriteria(Criteria.where("openid").is(vo.getOpenid()));
        if(!ObjectUtils.isEmpty(vo.getOrderStatus())) {
            query.addCriteria(Criteria.where("orderStatus").is(vo.getOrderStatus()));
        } else {
            query.addCriteria(Criteria.where("orderStatus").ne(0));
        }
        if(!ObjectUtils.isEmpty(vo.getOrderType())) {
            query.addCriteria(Criteria.where("orderType").is(vo.getOrderType()));
        }
        if(ObjectUtils.isEmpty(startEndTime.getStartTime())){
            query.addCriteria(Criteria.where("createTime").lte(startEndTime.getEndTime()));
        } else {
            query.addCriteria(Criteria.where("createTime").gte(startEndTime.getStartTime()).lte(startEndTime.getEndTime()));
        }
        query.with(Sort.by(Sort.Direction.DESC, "createTime"));
        List<PayOrderInfoQueryResp> payOrderInfoQueryResps = mongoTemplate.find(query,PayOrderInfoQueryResp.class,"pay_order_info");
        ResponseMap res = ResponseMap.success();
        if(CollectionUtils.isEmpty(payOrderInfoQueryResps)) {
            return res;
        } else {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DateUtil.FORMAT_1);
            Map<String, List<PayOrderInfoQueryResp>> groupedOrders = payOrderInfoQueryResps.stream()
                    .collect(Collectors.groupingBy(order ->
                            LocalDateTime.parse(order.getOrderTime(), formatter).format(DateTimeFormatter.ofPattern("yyyy-MM"))
                    ));
            List<PayOrderInfoDataQueryResp> payOrderInfoDataQueryResps = new ArrayList<>();
            groupedOrders.forEach((date,orderResps)->{
                PayOrderInfoDataQueryResp dataResp = new PayOrderInfoDataQueryResp();
                dataResp.setDate(date);
                dataResp.setPayOrderInfoQueryResps(orderResps);
                payOrderInfoDataQueryResps.add(dataResp);
            });
            res.put("payOrderInfoDataQueryResps",payOrderInfoDataQueryResps);
            return res;
        }
    }
}
